import random
import re
from playwright.sync_api import Playwright, sync_playwright, expect
import os
from WalmartContentSpinner import process_product_content
from process_amazon2 import human_like_scroll
from public_xue import array_to_string, get_filename_part, sleep
import time
import math
import traceback
import asyncio
import uuid
from random import randint
import datetime   
from datetime import datetime
from PyQt5.QtGui import QTextCharFormat, QColor
from playwright.async_api import async_playwright
import json
import logging
from bs4 import BeautifulSoup

class miaoshou_auto(object):
    def __init__(self, textUpdateSignal,excelhelper_instance):
        self.textUpdateSignal = textUpdateSignal
        self.currentpage=1
        self.excelhelper_instance=excelhelper_instance

        
        
    def miaoshou_login(self,page):
        """修复线程问题"""
        config_dict=self.read_jobs_config()
        self.useraccount=config_dict['miaoshou_account']
        self.userpassword=config_dict['miaoshou_password']
        self.brand=config_dict['brand']
        try:
            # 添加捕获所有可能的异常
            try:
                client = page.context.new_cdp_session(page)
                client.send("Network.enable")
                client.send("Network.emulateNetworkConditions", {
                    "offline": False,
                    "downloadThroughput": 500 * 1024 / 8,  # 限制下载速度
                    "uploadThroughput": 500 * 1024 / 8,    # 限制上传速度
                    "latency": 20  # 延迟
                })
                for ix in range(2):
                    try:
                        page.goto("https://erp.91miaoshou.com/",timeout=2000,wait_until="networkidle")
                        print(f"加载{ix+1}妙手网站成功")
                        break
                    except Exception as e:
                        print(f"尝试{ix+1}后妙手登录失败: {e}")
                        traceback.print_exc()
                    sleep(random.random()*2)
                url=page.url 
                if 'welcome' not in url.lower():
                    page.get_by_role("textbox", name="手机号/子账号/邮箱").click()
                    page.get_by_role("textbox", name="手机号/子账号/邮箱").click() 
                    page.get_by_role("textbox", name="手机号/子账号/邮箱").fill(self.useraccount)
                    page.get_by_role("textbox", name="手机号/子账号/邮箱").press("Tab")
                    page.get_by_role("textbox", name="密码").click() 
                    page.get_by_role("textbox", name="密码").fill(self.userpassword) 
                    page.get_by_role("button", name="立即登录").click()
                    if page.get_by_label("关闭此对话框").first:
                        page.get_by_label("关闭此对话框").first.click()
                    if page.get_by_label("关闭此对话框"):
                        page.get_by_label("关闭此对话框").click()
                    if page.get_by_placeholder("快速搜索功能"):
                        page.get_by_placeholder("快速搜索功能").click()
                else:
                    self.textUpdateSignal.emit("妙手登录成功！等到看见未发布后，点击才可以点击妙手上新")
            except Exception as e:
                traceback.print_exc()
                if "cannot switch to a different thread" in str(e):
                    # 如果是线程错误，重试或提供错误信息
                    print(f"线程切换错误，可能需要重启应用: {e}")
            for ix in range(2):
                try:
                    page.goto("https://erp.91miaoshou.com/walmart/collect_box/items",timeout=2000,wait_until="networkidle")
                    sleep(random.random()*0.5)
                    break
                except Exception as e:
                    print(f"点击产品失败: {e}")
                    traceback.print_exc()
                    print('开始读取数据')

            self.upc_list_no_used=self.get_upc_list(page,None)
            self.upc_list_used=[]

            # self.monitor_add_button(page)

            # sql = f"SELECT productid,keywords,detail1,detail2,detail3,detail4,detail5,weight FROM app_product_xue  where can_pubished=1 and uploadtowalmartdate is null   "
            sql = f"SELECT asin,detail1,detail2,detail3,detail4,detail5 FROM app_asinsupload_xue  where processdate is not null      "
            result = self.excelhelper_instance.query_one(sql)
            self.asin_list = [record['asin'] for record in result]
            # self.weight_list = [record['weight'] for record in result]
            # self.keywords_list = [record['keywords'] for record in result]
            self.detail1_list = [record['detail1'] for record in result]
            self.detail2_list = [record['detail2'] for record in result]
            self.detail3_list = [record['detail3'] for record in result]
            self.detail4_list = [record['detail4'] for record in result]
            self.detail5_list = [record['detail5'] for record in result]
            self.detail_list = [self.detail1_list,self.detail2_list,self.detail3_list,self.detail4_list,self.detail5_list]
            sql = "SELECT label, inputvalue, input_type FROM app_categorydefault_xue"
            self.catogorydefaultlist=self.excelhelper_instance.query_one(sql)
            page.wait_for_load_state('domcontentloaded')
        
            # 确保body元素存在
            page.wait_for_selector('body')
            # page.evaluate('document.body.style.zoom = 0.7')

            return True
        except Exception as e:
            print(f"妙手登录出现异常，已捕获处理: {e}")
            traceback.print_exc()

            return False

    def read_jobs_config(self):    
        config_dict={} 
        curpath=os.getcwd()
        file_path=os.path.join(curpath, 'autoconfig.ini')
        try:
            with open(file_path, 'r', encoding='utf-8') as file:
                for line in file:
                    # 去除空白字符
                    line = line.strip()
                    if line and '=' in line:
                        key, value = line.split('=', 1)
                        key = key.strip()
                        value = value.strip()
                        config_dict[key]=value
                                                 
            return config_dict
        except FileNotFoundError:
            print(f"文件 {file_path} 不存在")
            return []
        except Exception as e:
            print(f"读取文件时发生错误: {e}")
            return []
    def get_upc_list(self,page,  upc_list_used):
        try:
            if upc_list_used and len(upc_list_used)>0:
                upcs=array_to_string(upc_list_used)
                sqlupc_update =f'update app_upc_xue set upload_at=now() where upc in ({upcs})'
                self.excelhelper_instance.execute(sqlupc_update)
            sqlupc='select * from app_upc_xue where upload_at is null'
            upc_list_result=self.excelhelper_instance.query_one(sqlupc)
            upc_list_no_used=[record['upc'] for record in upc_list_result]
            upc_list_used=[]
        except Exception as e:
            print(f"获取UPC列表失败: {e}")
            traceback.print_exc()
            return []
        return upc_list_no_used

    def miaoshou_process_upload(self,page):
        """
        读取妙手ERP采集箱中的商品，对比数据库中的ASIN，选中匹配的商品
        
        Args:
            page: playwright页面对象
            self.excelhelp_instance: 数据库连接助手（用于检查ASIN是否存在）
        """
        
        print("开始读取采集箱商品信息...")
        
        # 确保页面已加载
        try:
            # page.goto("https://erp.91miaoshou.com/walmart/collect_box/items", timeout=6000)
            page.bring_to_front()
        except Exception as e:
            print(f"页面加载失败: {e}")
            traceback.print_exc()
        sleep(random.random()*0.5)
        print("采集箱页面加载完成")
        sleep(random.random())
        rowsnumber=0
        locator = page.locator('label').filter(has_text=re.compile(r'未发布 \(\d+\)'))
        try:
            if locator.count():
                locator.first.click()   
        except Exception as e:
            print(f"点击未发布失败: {e}")
            traceback.print_exc()
        trytimes=0
        while locator.count() == 0 or locator.is_visible() ==False:
            sleep(random.random()* 2)
            print(f"{trytimes}次等待未发布元素出现")
            trytimes+=1
            if trytimes>3:
                break
        # sleep(random.random()* 30)
        if locator.count() > 0:
        # 获取第一个匹配元素的文本内容
            element_text = locator.first.text_content()
            # 使用正则表达式提取数字
            match = re.search(r'\d+', element_text)
            if match:
                number = match.group()
                print(f"未发布后面的数字是: {number}")
                rowsnumber=int(number)
            else:
                print("未找到匹配的数字")
        else:
            print("未找到匹配的元素")

        for _ in range(10):  # 可以根据页面长度调整次数
            page.keyboard.press('PageDown')
            page.wait_for_timeout(random.randint(150,250))
        
                # 确保到达底部
        page.keyboard.press('End')
        # page.set_viewport_size({"width": 1280, "height": 1080})

        page.wait_for_timeout(random.randint(300,800))
     
        for ix in range(1):
            try:
                page.wait_for_selector(".el-pagination__sizes .el-select", state='visible', timeout=5000)
                page.locator(".el-pagination__sizes .el-select").click(force=True) #        page.evaluate("window.scrollTo(0, document.body.scrollHeight)") 
                sleep(random.random()*0.2)
                break
            except Exception as e:
                print(f"点击每页显示失败: {e}")
                traceback.print_exc()
           
       
        # 选择指定条数
        items_selector = f".el-select-dropdown__item:has-text('10条/页')"
        if page.is_visible(items_selector):
            page.locator(items_selector).click()
            print(f"已设置每页显示 10 条商品")
        #  # 处理采集箱中的所有商品
        # 滚动到顶部
        page.keyboard.press('Home')
        page.wait_for_timeout(random.randint(800,1200)) 
        # for ix in range(3):
        #     try:
        #         page.wait_for_selector(".jx-pro-virtual-table__row",state='visible')
        #         break
        #     except Exception as e:
        #         print(f"等待商品行出现失败: {e}")
        #         traceback.print_exc()
        #         sleep(random.random()*2)
        # 获取初始可见行数

        print(f"初始可见行数: {rowsnumber}")
        # 
         
        page.evaluate("window.scrollTo(0, document.body.scrollHeight);")
        sleep(random.random()*0.5)
        page.evaluate("window.scrollTo(0, 0);")
        timesleep=1500
        sleep(random.random()*0.6)

        # 滚动加载更多行并处理
        pagecount=10
        max_scroll_attempts = 30  # 防止无限循环
        scroll_attempts = 0
        uploaded_asins=[]
        results=[]
        
        total_pages=math.ceil(rowsnumber/pagecount)
        dealpages=total_pages
        self.currentpage=1
        for ix in range(dealpages):
            resultx=self.process_single_row(page, self.excelhelp_instance,ix+1,total_pages,rowsnumber)
            results.append(resultx)
        self.textUpdateSignal.emit(f"完成处理！共处理 {rowsnumber} 行")
        asins=[]
        self.upc_list_used=[]
        for result in results:
            if result and result['asins'] and len(result['asins'])>0:
                for resultx in result['asins']:
                    asins.append({'asin':resultx})
                self.upc_list_used.extend(result['upc_list_used'])
        
        if results and len(asins)>0:
        # 批量选择后，设置价格，暂时批量0.95折
            asins_list= array_to_string(asins)
            # asins_list=asins_list[-1]
            # sql_update=f'update app_product_xue set uploadtowalmartdate=now()  where productid in ({asins_list})'
            # self.excelhelp_instance.execute(sql_update)
            sql_update=f'insert into sku_keywords_history(sku,keywords,opdate) values(:asin,"uploadtowalmart",now())'
            self.excelhelp_instance.execute(sql_update,asins)     
        upc_list_no_used=self.get_upc_list(page,  self.upc_list_used)
        print(f"完成处理！共读取 {rowsnumber} 行")       
        timesleep=500
    def process_single_row(self,page, currentpage,total_pages,rowsnumber):
        timesleep=500
        asin=''
        print(2)
        processed_asin=[]
        startrow=1
        print(3)
        current_upc=''
        pagecount=10
        if currentpage<total_pages or rowsnumber==pagecount*total_pages:
            rowsnumber=pagecount
        else:
            rowsnumber=rowsnumber%pagecount
        if currentpage!=1 and currentpage!=total_pages:
            for _ in range(10):  # 可以根据页面长度调整次数
                page.keyboard.press('PageDown')
                page.wait_for_timeout(200)
        
                # 确保到达底部
            page.keyboard.press('End')

            page.wait_for_timeout(random.randint(300,800))
            page.wait_for_selector(f"//ul[@class='el-pager']/li[@class='number' and text()='{currentpage}']", state='visible', timeout=5000)
            page.locator(f"//ul[@class='el-pager']/li[@class='number' and text()='{currentpage}']").click()
        
            
            # 滚动到顶部
            page.keyboard.press('Home')
            page.wait_for_timeout(random.randint(800,1200))
        
        # import asyncio
        page.evaluate("window.scrollTo(0, document.body.scrollHeight)") 
        sleep(random.random()*2)
        page.evaluate("window.scrollTo(0, 0)")
        sleep(random.random()*2)
        page.evaluate("window.scrollTo(0, document.body.scrollHeight)") 
        page.evaluate("window.scrollTo(0, document.body.scrollHeight)") 
        page.evaluate("window.scrollTo(0, 0)")
        page.evaluate("window.scrollTo(0, document.body.scrollHeight)") 
        rows = page.query_selector_all('.vue-recycle-scroller__item-view')

        remark_buttons = page.query_selector_all('.J_collectBoxRemark')
        trytimes=0  
        while len(remark_buttons)!=len(rows) and len(remark_buttons)<rowsnumber:
            page.evaluate("window.scrollTo(0, 0)")
            sleep(random.random()*2)
            page.keyboard.press('Tab')
            sleep(random.random()*0.2)
            page.keyboard.press('ArrowDown')    
            sleep(random.random()*0.2)
            page.evaluate("window.scrollTo(0, document.body.scrollHeight)") 
            sleep(random.random()*2)
            rows = page.query_selector_all('.vue-recycle-scroller__item-view')
            remark_buttons = page.query_selector_all('.J_collectBoxRemark')
            trytimes+=1
            print(f"尝试{trytimes}次，仍然没有加载完成")
            if trytimes>3:
                break
        category_title_list=[]
        for ixx,row in enumerate(rows):   
            category_element = row.query_selector('.jx-pro-tag.category-tag span[title]')
            if category_element:
                category_title = category_element.get_attribute('title').replace('>','_').replace(' ','').replace('&','')
            else:
                category_title=''
            category_title_list.append(category_title) # 
        i=0        
        while i < len(category_title_list):
            if category_title_list[i] == '':
                del category_title_list[i]
                del rows[i]
            else:
                i = i + 1
        for ix in range(len(category_title_list)-rowsnumber):             
            del rows[0]     
        for ixx,row in enumerate(rows):   
            try:

                if page.get_by_role("button", name="保存修改").is_visible():
                    sleep(random.random()*0.6)
                    page.get_by_role("button", name="取消").first.click()   
                    sleep(random.random()*0.6)
                    print(f'第{rowindex}行',3)           

                    if page.locator("button.el-button.el-button--default.el-button--small.el-button--primary").count() > 0:
                        page.locator("button.el-button.el-button--default.el-button--small.el-button--primary").click()
                    sleep(random.random()*0.6)
                rowindex=ixx+1
                print(4)

                self.ensure_row_visible(page,row)
                row.scroll_into_view_if_needed()
                print(rowindex,5)  
                sleep(random.random()*0.5)
                print(rowindex,6)    
                category_title=category_title_list[ixx]
                title_selector = f"div:nth-child({rowindex}) > .jx-pro-virtual-table__row .title-edit .title-wrap"
                category_element = row.query_selector('.jx-pro-tag.category-tag span[title]')
                category_title=category_element.get_attribute('title').replace('>','_').replace(' ','').replace('&','')
                title=''
                title_element = row.query_selector('.title-wrap.J_editGoodsTitle span')
                if title_element:
                    title_element.scroll_into_view_if_needed()
                    title = title_element.text_content()
                titlememo=title
                if len(titlememo) > 50:
                    words_memo   = titlememo.split()
                    titlememo= ' '.join(words_memo[:5])
                titlememo=titlememo+ '...'
                resultai=process_product_content(title,'')
                newtitle=resultai['shuffled_title']
                if category_title=='':
                    strtip=f'第{rowindex}行,{title},类目为空，跳过不处理'
                    self.textUpdateSignal.emit(strtip)
                    strmemo=f'{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}，{titlememo},没有找到类目'
                    self.add_remark_with_retry(page,row,strmemo)
                    continue
                print(rowindex,7)    
                
                # print(rowindex,8)    
                amazon_element=row.query_selector('.goods-info-item .goods-info-source')
                if not  amazon_element :
                    print(title,category_title,f"process_single_row，没有找到亚马逊链接")
                    continue
                print(rowindex,9)    
                sleep(random.random()*0.6)
                amazon_url = amazon_element.get_attribute("href")
                if not amazon_url:
                    print("此行没有找到亚马逊链接")
                    strmemo=f'{datetime.now().strftime('%Y-%m-%d %H:%M:%S')},第{rowindex}行,{titlememo}，没有找到亚马逊链接'
                    self.add_remark_with_retry(page,row,strmemo)
                    # page.locator('//textarea[@class="el-textarea__inner"]').fill(strmemo)
                    # page.get_by_role("button", name="确定").click()
                    continue
                asin_match = re.search(r"/dp/([A-Z0-9]{10})", amazon_url)
                print(rowindex,10)    
                if not asin_match:
                    print(f"无法从链接提取ASIN: {amazon_url}")
                    continue
                asin = asin_match.group(1)
                # sql=f"select * from app_product_xue where productid='{asin}'"
                # result=self.excelhelp_instance.query_one(sql) 
                asinindex=-1
                is_in_database = False
                strindatabase='《----不在数据库中*****'
                if asin in self.asin_list:
                    is_in_database = True
                    asinindex=self.asin_list.index(asin)
                    strindatabase='在数据库中----》'
                else:
                    strmemo=f'{datetime.now().strftime('%Y-%m-%d %H:%M:%S')},{asin}，{titlememo}，没有在数据库中'
                    # page.locator('//textarea[@class="el-textarea__inner"]').fill(strmemo)
                    # page.get_by_role("button", name="确定").click()
                    self.add_remark_with_retry(page,row,strmemo)
                # 获取当前行的复选框
                # keywords=self.keywords_list[asinindex]
                print(rowindex,12)    

                # checkbox =row.query_selector('.el-checkbox__original:not([aria-hidden="true"])')
                checkbox=row.query_selector('.el-checkbox')

                if not checkbox:
                    print(f"未在当前行{rowindex}找到可见的checkbox")
                else:
                    print(f"在当前行{rowindex}找到可见的checkbox")
                self.textUpdateSignal.emit(f'asin{strindatabase}，当前行：{rowindex}，提取到ASIN: {asin}，category_text: {category_title}，title: {titlememo}')       
                if asin in self.asin_list:

                     
                    print(rowindex,14)    
                    try:
                        checkbox.wait_for_element_state('visible',timeout=5000)
                        checkbox.evaluate("""checkbox => {
                            checkbox.click();
                            checkbox.checked = true;
                            checkbox.dispatchEvent(new Event('change', { bubbles: true }));
                        }""")
                    except Exception:
                        traceback.print_exc()
                        checkbox.check(force=True)
 
                    checkbox=row.query_selector('.el-checkbox')
                    is_checked = checkbox.evaluate('node => node.checked')
                    if is_checked:
                        print("成功勾选checkbox")
                    else:
                        print("勾选失败")
                    # page.locator(f"div:nth-child({rowindex}) > .jx-pro-virtual-table__row > div > .el-checkbox > .el-checkbox__input > .el-checkbox__inner").click()
                    sleep(random.random()*random.randint(2,3))
                    page.get_by_role("button", name="设置售价").click()
                    page.get_by_role("radio", name="使用公式：").click()
                    page.get_by_placeholder("倍数").click()
                    page.get_by_placeholder("倍数").fill("0.98")
                    page.get_by_role("button", name="应用至选中").click()
                    page.get_by_role("button", name="关闭", exact=True).click()
                    sleep(random.random()*0.6)

                    try:
                        # checkbox.wait_for_element_state('visible')
                        checkbox.evaluate("""checkbox => {
                            checkbox.click();
                            checkbox.checked = true;
                            checkbox.dispatchEvent(new Event('change', { bubbles: true }));
                        }""")
                    except Exception:
                        # 如果JavaScript点击失败，尝试使用force选项
                        checkbox.check(force=True)
                    
                    # 验证是否成功选中
                    is_checked = checkbox.evaluate('node => node.checked')
                    if not is_checked:
                        checkbox.check()
                    page.get_by_role("button", name="引用模板").click()
                    sleep(random.random()*1)  # 增加等待时间
                    print(rowindex,15)      

                    page.get_by_placeholder("请选择模板").click()
                    sleep(random.random()*2)  # 等待下拉框展开

                    template_name=f"{category_title}_auto"
                    elements_template = page.get_by_text(template_name).all()
                    try:
                        if len(elements_template) > 0:  # 使用 len() 替代 count()
                            # dropdown_selector = '.el-select-dropdown.el-popper:not([style*="display: none"]) .el-select-dropdown__wrap'
                            # page.wait_for_selector(dropdown_selector, state='visible', timeout=10000)
                            sleep(random.random()*1)  # 给予额外时间让UI完全展开
                            dropdown_items = page.locator('.el-select-dropdown__item span').filter(has_text=template_name)
                            dropdown_items.first.scroll_into_view_if_needed()
                            sleep(random.random()*2)
                            dropdown_items.first.click()
                            sleep(random.random()*1)
                            apply_button = page.get_by_role("button", name="应用至选中")
                            apply_button.wait_for(state='visible', timeout=5000)
                            apply_button.click()
                            sleep(random.random()*1.1)
                            close_button = page.get_by_role("button", name="关闭", exact=True)
                            close_button.wait_for(state='visible', timeout=5000)
                            close_button.click()
                        else:   
                            print(f"未找到模板: {template_name}")
                            page.get_by_text("批量引用模板", exact=True).first.click()
                            sleep(random.random()*1.1)
                            page.get_by_role("button", name="取消").first.click()
                            sleep(random.random()*1.1)
                            strmemo=f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")},第{rowindex}行,{titlememo}，先建立模板名称：{template_name} 后，（模版里预留5点输入）接口可以自动编辑'
                            self.add_remark_with_retry(page,row,strmemo)
                            checkbox.uncheck()
                            continue
                    except Exception as e:
                        print(f"选择模板时出错: {e}")
                        traceback.print_exc()
                        continue
                    print(rowindex,16)    
                        
                    sleep(random.random()*1.1)
                    page.locator(f"div:nth-child({rowindex}) > .jx-pro-virtual-table__row > div:nth-child(8) > .operate-box > .el-button-group > button").first.click()                
                    sleep(random.random()*0.6)
                    page.locator("li").filter(has_text="基本信息").locator("div").click()
                    textareas = page.locator('textarea.el-textarea__inner')
                    playwright_count = textareas.count()
                    print(rowindex,17)    

                    for i in range(5):
                        if self.detail_list[i][asinindex]:
                            textareas.nth(i+1).fill(self.detail_list[i][asinindex])
                    # 以下为5点描述
                    page.locator("li").filter(has_text="其他信息").locator("div").click()
                    sleep(random.random()*0.6)
                    print(rowindex,18)    
                    page.locator(".other-info-box > div > .el-form-item__content > .edit-field-content > .jx-pro-input > .el-input__inner").first.click()
                    sleep(random.random()*0.6)
                    page.locator(".other-info-box > div > .el-form-item__content > .edit-field-content > .jx-pro-input > .el-input__inner").first.fill(self.brand)
                    sleep(random.random()*0.6)
                    page.locator(".other-info-box > div > .el-form-item__content > .edit-field-content > .jx-pro-input > .el-input__inner").first.press("Tab")
                    sleep(random.random()*0.6)
                    random_uuid = uuid.uuid4()
                    # 获取 UUID 的前 8 个字符
                    part_of_uuid = str(random_uuid)[:8]
                    print(part_of_uuid)
                    print(rowindex,19)                         
                    sleep(random.random()*0.6)
                    page.locator("div:nth-child(5) > .el-form-item__content > .edit-field-content > .jx-pro-input > .el-input__inner").click()
                    sleep(random.random()*0.6)
                    # if self.weight_list[asinindex] and self.weight_list[asinindex]!='' and self.weight_list[asinindex]!=None:
                    #     page.locator("div:nth-child(5) > .el-form-item__content > .edit-field-content > .jx-pro-input > .el-input__inner").fill(str(round(float(self.weight_list[asinindex] *2.22),2)))   
                    sleep(random.random()*0.6)
                    # page.locator("div:nth-child(7) > .el-form-item__content > .edit-field-content > .el-select > .el-input > .el-input__inner").first.click()
                    sleep(random.random()*0.6)
                    # page.get_by_role("tablist").get_by_text("1").click()
                    print(rowindex,20)    

                    # while True:
                    #     sku_count = page.locator('.sku-attribute-option').count()-1
                    #     print(f"当前SKU数量: {sku_count}")
                    #     if sku_count <= 6:
                    #         print("SKU数量已经达到或小于6个，停止删除")
                    #         break
                    #     try:
                    #         last_delete_button = page.locator('.sku-attribute-option').nth(sku_count - 3).locator('.el-icon-delete')
                    #         last_delete_button.wait_for(state='visible', timeout=5000)
                    #         last_delete_button.scroll_into_view_if_needed()
                    #         sleep(random.random() * 1 + 0.5)
                    #         last_delete_button.click()
                    #         print(f"正在删除第 {sku_count} 个SKU")
                    #         sleep(random.random() * 1 + 0.5)
                    #         new_count = page.locator('.sku-attribute-option').count()-1
                    #         if new_count >= sku_count:
                    #             print(f"删除可能失败，重试...")
                    #             page.evaluate("""(index) => {
                    #                 const deleteButtons = document.querySelectorAll('.el-icon-delete');
                    #                 if (deleteButtons[index]) {
                    #                     deleteButtons[index].click();
                    #                 }
                    #             }""", sku_count - 1)
                    #             sleep(random.random()   + 0.5)
                    #     except Exception as e:
                    #         print(f"删除SKU时出错: {e}")
                    #         traceback.print_exc()
                    #         sleep(random.random() * 2)
                    #         continue
                    #     final_count = page.locator('.sku-attribute-option').count()
                    #     print(f"删除完成，最终SKU数量: {final_count}")
                        
                    lastlen=0
                    input_elements = page.locator('input.el-input__inner[minlength="1"][maxlength="14"]')
                    scrollable_container = page.locator('.el-scrollbar__wrap').first
                    old_count=1
                    new_counts = input_elements.count()
                    print(f"找到的总输入框数量: {new_counts}")
                    while True:
                        for i in range(new_counts):
                            try:
                                current_input = input_elements.nth(i)
                                # 确保当前输入框可见
                                current_input.scroll_into_view_if_needed()
                                page.evaluate("""(element) => {
                                    if (element) {
                                        element.scrollIntoView({behavior: 'smooth', block: 'center'});
                                    }
                                }""", current_input)                               
                                sleep(random.random() * 1.2)                                
                                orginupc = current_input.input_value()
                                print(f"处理第 {i+1}/{new_counts} 个输入框，原始UPC: {orginupc}")
                                current_input.fill('')
                                current_upc = ''
                                if not self.upc_list_no_used   :
                                    self.upc_list_no_used = self.get_upc_list(page,  self.upc_list_used)
                                    self.upc_list_used = []
                                if self.upc_list_no_used  :
                                    current_upc = self.upc_list_no_used.pop(0)
                                    print(f"使用新的UPC: {current_upc}")
                                    self.upc_list_used.append(current_upc)
                                    current_input.type(current_upc)
                                    current_input.scroll_into_view_if_needed()
                                    page.keyboard.press('Tab')
                                    sleep(random.random()*0.2)
                                    page.keyboard.press('PageDown')    
                                    sleep(random.random()*0.2)
                                    sleep(random.random() * 0.6)
                                sleep(random.random() * 0.5)
                            except Exception as e:
                                print(f"处理第 {i+1} 个输入框时出错: {e}")
                                traceback.print_exc()
                                continue
                        old_count=new_counts
                    input_elements = page.locator('input.el-input__inner[minlength="1"][maxlength="14"]')
                    new_counts=input_elements.count()
                    if new_counts==old_count:
                        break
                    
                    page.get_by_role("button", name="保存修改").click()
                    sleep(random.random()*2)
                    page.get_by_role("button", name="取消").first.click()   
                    sleep(random.random()*2)
                    print(rowindex,23)           

                    if page.locator("button.el-button.el-button--default.el-button--small.el-button--primary").count() > 0:
                        page.locator("button.el-button.el-button--default.el-button--small.el-button--primary").click()
                    sleep(random.random()*0.6)
                    is_checked = checkbox.evaluate('node => node.checked')
                    if not is_checked:
                        checkbox.check()
                    # page.locator(f"div:nth-child({rowindex}) > .jx-pro-virtual-table__row > div:nth-child(8) > .operate-box > .el-button-group > button:nth-child(4)").click()
                    page.wait_for_timeout(500)
                    print(rowindex,25)    
            
                    strmemo=f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}，你好，这是程序自动完善产品信息的,这个信息已编辑完毕，你可以核对后发布。"
                    # if new_counts>6:
                    #     strmemo=f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}，你好，这个产品超过了6个SKU，请删除多余的SKU。只保留6个SKU。"
                    self.add_remark_with_retry(page,row,strmemo)
                    print(f"已成功为第{rowindex}行,{asin},{title}添加备注内容")
                    page.locator(f"div:nth-child({rowindex}) > .jx-pro-virtual-table__row > div:nth-child(8) > .operate-box > .operate-mark").click()
                    print(rowindex,26)    
                    is_checked = checkbox.evaluate('node => node.checked')
                    if   is_checked:
                        checkbox.uncheck()
                    processed_asin.append(asin)
            except Exception as e:
                traceback.print_exc()
                continue
        return {'asins':processed_asin,'upc_list_used':self.upc_list_used}
    # 选择器根据你的HTML结构
        
    def monitor_5_features(self,page):
 
        textareas = page.query_selector_all('textarea.el-textarea__inner:not([attributename="shortDescription"])')
        all_valid=True
        xtimes=0
        if  len(textareas)  < 5:
            print(f"只有{len(textareas)}个五点输入框，数量不足5个")
            all_valid=False
        elif len(textareas) >= 5:
            # 检查每个 textarea 的内容长度
            for i, textarea in enumerate(textareas):
                value =  textarea.evaluate('el => el.value')
                if value is None or len(value.strip()) < 4:
                    print(f"第{i+1}个textarea内容不足4个字符: '{value}'")
                    all_valid = False
                    xtimes=xtimes+1
            if all_valid or xtimes<4:
                print(f"有5个textarea，且{xtimes}个五点描述内容长度都不少于4个字符,不需要处理")
                return 
            else:
                print("有内容不满足要求")
 
            
        page.locator("li").filter(has_text="类目&属性").locator("div").click()  
        sleep(random.random()*0.6)
        labels = []
        input_fields = []
        label_text=''
        form_container = page.query_selector('.sub-attribute-list') 
        form_items = form_container.query_selector_all('.el-form-item')
        for categoryindex,   form_item in enumerate( form_items)    :
            label_element = form_item.query_selector('.el-form-item__label')
            label_text=label_element.text_content().strip()
            input_type = "unknown"
            input_element = form_item.query_selector('.el-input__inner')
            current_value=''
            if input_element:
                # 检查是否是只读的（下拉框）
                inputvalue=''
                found=False
                is_readonly = input_element.get_attribute('readonly')
                for key in self.catogorydefaultlist:
                    processed_key = key['label'].strip().lower().replace(' ','').replace(':','')
                    if processed_key == label_text.lower().strip().replace(' ','').replace(':',''):
                        inputvalue=key['inputvalue']
                        found=True
                        break
                if found:
                    if is_readonly:
                        input_type = "select"
                        input_element.scroll_into_view_if_needed()
                        input_element.click()
                        sleep(random.random()*0.6)
                        try:
                            page.get_by_role("tablist").get_by_text(inputvalue).click(timeout=1500)     
                            sleep(random.random()*0.6)
                        except Exception as e:
                            traceback.print_exc()
                            print(f"选择{inputvalue}时出错: {e}")
                            try:
                                page.get_by_text(inputvalue, exact=True).click(timeout=1500)   
                                sleep(random.random()*0.6)
                            except Exception as e:
                                traceback.print_exc()
                                print(f"选择{inputvalue}时出错: {e}")
                    else:
                        input_type = "input"
                        input_element.scroll_into_view_if_needed()
                        input_element.fill(inputvalue)
                        sleep(random.random()*0.6)
        page.evaluate("""
                () => {
                    const el = document.querySelector('.source-url-input .el-input__inner');
                    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });
                }
            """)
        for ix3 in range(5-len(textareas)):
            page.wait_for_selector('button.add-button', state='visible' ,timeout=5000)
            add_button = page.query_selector('button.add-button')
            if add_button:
                page.evaluate("""
                        () => {
                            document.querySelectorAll('.el-loading-mask, .el-overlay, .mask').forEach(el => el.remove());
                        }
                    """)
                add_button.scroll_into_view_if_needed()
                # 点击按钮
                page.evaluate('el => el.click()', add_button)
                sleep(random.random()*0.6)
                print(f"{ix3+1}次，已点击添加更多按钮")
            else:
                print("未找到添加更多按钮")
        asinindex=-1
        asinvalue = page.eval_on_selector(
            '.source-url-input .el-input__inner',
            'el => el.value'
        )
        print("输入框内容:", asinvalue)
        match = re.search(r'/dp/([A-Z0-9]{10})', asinvalue)
        asin=''
        if match:
            asin = match.group(1)
            print("ASIN:", asin)
        else:
            print("未找到ASIN")

        # 以下为5点描述
        page.locator("li").filter(has_text="其他信息").locator("div").click()
        sleep(random.random()*0.6)
        page.locator(".other-info-box > div > .el-form-item__content > .edit-field-content > .jx-pro-input > .el-input__inner").first.click()
        sleep(random.random()*0.6)
        page.locator(".other-info-box > div > .el-form-item__content > .edit-field-content > .jx-pro-input > .el-input__inner").first.fill(self.brand)
        sleep(random.random()*0.6)
        page.locator(".other-info-box > div > .el-form-item__content > .edit-field-content > .jx-pro-input > .el-input__inner").first.press("Tab")
        sleep(random.random()*0.6)
        random_uuid = uuid.uuid4()
        # 获取 UUID 的前 8 个字符
        part_of_uuid = str(random_uuid)[:8]
        print(part_of_uuid)
        sleep(random.random()*0.6)
        # page.locator("div:nth-child(5) > .el-form-item__content > .edit-field-content > .jx-pro-input > .el-input__inner").click()
        sleep(random.random()*0.6)
        # if self.weight_list[asinindex] and self.weight_list[asinindex]!='' and self.weight_list[asinindex]!=None:
        #     page.locator("div:nth-child(5) > .el-form-item__content > .edit-field-content > .jx-pro-input > .el-input__inner").fill(str(round(float(self.weight_list[asinindex] *2.22),2)))   
        sleep(random.random()*0.6)
        # page.locator("div:nth-child(7) > .el-form-item__content > .edit-field-content > .el-select > .el-input > .el-input__inner").first.click()
        sleep(random.random()*0.6)
        # page.get_by_role("tablist").get_by_text("1").click()
        print(20)    
        page.get_by_text("销售属性", exact=True).click()   
        page.keyboard.press('PageDown')
        sleep(random.random()*0.6)
        # page.wait_for_selector('.sku-attribute-options', state='visible', timeout=5000)
        sleep(random.random() * 2)
        # sku_count = page.locator('.sku-attribute-option').count()-1
        # self.textUpdateSignal.emit(f"sku数量为{sku_count}，开始删除多余的{sku_count-6}个sku")


        # delete_icons = page.query_selector_all('i.el-icon-delete.delete-icon')
        # print(f"找到 {len(delete_icons)} 个删除图标")
        
        total_rows=1
        total_rows = page.locator('.sku-attribute-option').count()-1
        row_height=60

        scroller_selector = '.vue-recycle-scroller__slot'

        row_index = 0
        if total_rows==-1:
            total_rows=1    
        trytimesx=0
        while True:
            if trytimesx>total_rows*6:
                    print(f"尝试{trytimesx}次，结束循环")
                    break
            # upc_inputs = page.query_selector_all('input.el-input__inner[minlength="1"][maxlength="14"]')
            selector = '''
                input.el-input__inner[minlength="1"][maxlength="14"]:not(
                    textarea.el-textarea__inner, 
                    [attributename="shortDescription"]
                )
            '''
            upc_inputs = page.query_selector_all(selector)
            if upc_inputs:
                for i, upc_input in enumerate(upc_inputs):
                    originupc=upc_input.input_value()
                    trytimesx=trytimesx+1
                    

                    # if row_index%5==1:
                    #     page.keyboard.press('PageDown')
                    #     sleep(random.random()*0.6)
                        
                    if originupc!='' and len(originupc)>8:
                        print(f"尝试{trytimesx}次，第{row_index+1}个，已经有了UPC: {originupc}")
                        # row_index+=1
                        upc_input.press('Tab')
                        continue
                    if  len(self.upc_list_no_used)==0:
                        self.upc_list_no_used=self.get_upc_list(page,  self.upc_list_used)
                    newupc=self.upc_list_no_used.pop(0)
                    upc_input.fill(str(newupc))
                    self.upc_list_used.append(newupc)
                    upc_input.press('Tab')
                    row_index+=1
                    print(f"第{row_index+1}行输入UPC: {newupc}")
            else:
                print(f"第{row_index+1}行未找到UPC输入框")
            page.keyboard.press('PageDown')
            sleep(random.random()*0.5)
            # 3. 滚动到下一屏
        self.upc_list_no_used=self.get_upc_list(page,  self.upc_list_used)
        asinindex=-1
        if asin in self.asin_list:
            asinindex=self.asin_list.index(asin)
        textareas = page.query_selector_all('textarea.el-textarea__inner:not([attributename="shortDescription"])')

        if asin and asin!='':
            for i in range(5):
                textareas[i].fill(self.detail_list[i][asinindex])
        self.textUpdateSignal.emit(f"{asin}，5点描述输入完成,UPC输入完成！")

    def add_remark_with_retry(self,page, row, memocontent,max_retries=3):
        """为指定行添加备注（带重试机制）"""
        stradd='*@*~><>'
        isok=False
        memovisible=False
        for retry in range(max_retries):
            if isok:
                break
            try:
                sleep(random.random() * 0.5)
                remark_button = row.query_selector('button.J_collectBoxRemark')
                if not remark_button:
                    print(f"未找到备注按钮: {memocontent}")
                    return False
                try:
                    if   memovisible==False:    
                        remark_button.click()
                except Exception as e:
                    traceback.print_exc()
                sleep(random.random() * 0.5)
                try:
                    textarea_selector = 'textarea.el-textarea__inner'
                    page.wait_for_selector(textarea_selector, state='visible', timeout=5000)
                    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    sleep(random.random() * 0.3)
                    input_boxes = page.locator('textarea.el-textarea__inner')
                    match input_boxes.count():
                        case 1:
                            input_boxes.wait_for(state='visible')
                            input_boxes.fill(memocontent + random.choice(stradd))
                        case 2:
                            input_box = input_boxes.nth(0)  # 这里假设用第一个，如果第二个符合需求就用 nth(1)
                            # 解决元素拦截指针事件的问题，等待覆盖元素消失
                            overlay_element = page.locator('div.el-dialog__wrapper.jx-pro-dialog.has-footer')
                            overlay_element.wait_for(state='hidden', timeout=5000)
                            input_box.wait_for(state='visible')
                            input_box.fill(memocontent + random.choice(stradd))
                            memovisible=True
                    confirm_button = page.get_by_role("button", name="确定")
                    if confirm_button.is_visible():
                        # for attempt in range(3):
                        confirm_button.click()
                        trytimes=0
                        while confirm_button.is_visible():
                            sleep(random.random() *4)
                            print(f"等待备注的确认按钮消失")
                            trytimes+=1
                            if trytimes>3:
                                try:
                                    cancel_button = page.locator('button:has-text("取消")')
                                    # 等待按钮可见
                                    cancel_button.wait_for(state='visible')
                                    # 点击按钮
                                    cancel_button.click()
                                except Exception as e:
                                    traceback.print_exc()
                        break
                        isok=True    
                            
                except Exception as e:
                    traceback.print_exc()
                    print(f"第 {retry + 1} 次添加备注失败: {e}")
                    if retry == max_retries - 1:  # 最后一次重试
                        print(f"添加备注最终失败: {memocontent}")
                        traceback.print_exc()
                        return False
                    sleep(1)  # 重试前等待
                    continue
                    
            except Exception as e:
                print(f"处理行时出错: {e}")
                traceback.print_exc()

                if retry == max_retries - 1:
                    return False
                continue
                
        return False
    def ensure_row_visible(self,page, row):
        """确保行元素完全加载并可见"""
        try:
            # 1. 等待行元素加载完成
            page.wait_for_selector('.vue-recycle-scroller__item-view', 
                                state='attached', 
                                timeout=5000)
            
            # 2. 使用 JavaScript 检查和等待元素可见
            is_visible = page.evaluate("""(row) => {
                return new Promise((resolve) => {
                    if (row && row.offsetParent !== null) {
                        resolve(true);
                        return;
                    }
                    
                    // 创建观察器检查元素可见性
                    const observer = new IntersectionObserver((entries) => {
                        observer.disconnect();
                        resolve(entries[0].isIntersecting);
                    });
                    
                    observer.observe(row);
                    
                    // 5秒后超时
                    setTimeout(() => {
                        observer.disconnect();
                        resolve(false);
                    }, 5000);
                });
            }""", row)
            
            return is_visible
            
        except Exception as e:
            print(f"确保行可见时出错: {e}")
            return False
